<template>
  <div class="roamDrawer-container" :class="[visible ? 'show' : 'hide']">
    <div class="roamDrawer-body">
      <div class="header">
        漫游<a-icon type="close" @click="handleClose()" />
      </div>
      <!-- 路径 -->
      <div class="body" v-if="!isRoute">
        <div class="add-route-btn" @click="handleAddRoute()">
          <a-icon type="plus" />
          新增路径
        </div>
        <div class="route-list">
          <div class="empty-tip" v-if="routeSource.length == 0">
            <a-empty :description="false" />
          </div>
          <div
            class="list-item"
            v-for="(item, index) in routeSource"
            :key="index"
          >
            <div class="name">
              <div class="name-text">{{ item.roamName }}</div>
              <div class="operate">
                <a-tooltip placement="top">
                  <template slot="title">
                    <span>编辑</span>
                  </template>
                  <a-icon type="edit" @click.stop="handleEditRoute(item)" />
                </a-tooltip>
                <a-tooltip placement="top">
                  <template slot="title">
                    <span>删除</span>
                  </template>
                  <a-icon type="delete" @click.stop="handleDelateRoute(item)" />
                </a-tooltip>
              </div>
            </div>
            <div class="desc">
              <div class="input-number">
                <a-input-number :step="1" v-model="item.speed" :precision="1" />
                <div class="unit">m/s</div>
              </div>
              <div class="play">
                <a-tooltip placement="top" v-if="!isPlay[item.uuid]">
                  <template slot="title">
                    播放
                  </template>
                  <icon-fonts
                    icon="icon-bofang"
                    @click.native.stop="handelPlay(item)"
                  ></icon-fonts>
                </a-tooltip>
                <a-tooltip placement="top" v-else>
                  <template slot="title">
                    暂停
                  </template>
                  <icon-fonts
                    icon="icon-bofang1"
                    @click.native.stop="handelPause(item)"
                  ></icon-fonts>
                </a-tooltip>
                <a-tooltip placement="top">
                  <template slot="title">
                    停止
                  </template>
                  <icon-fonts
                    icon="icon-stop-circle"
                    @click.native.stop="handelStop(item)"
                  ></icon-fonts>
                </a-tooltip>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 视口 -->
      <div class="body" v-else>
        <div class="viewport-header">
          <div class="name">视口列表</div>
          <div class="operate">
            <a-tooltip placement="top">
              <template slot="title">
                <span>添加视口</span>
              </template>
              <icon-fonts
                icon="icon-add"
                @click.native.stop="handleAddViewPort()"
              ></icon-fonts>
            </a-tooltip>
            <a-tooltip placement="top" v-if="!isPlay['viewportRoam_uuid']">
              <template slot="title">
                <span>播放</span>
              </template>
              <icon-fonts
                icon="icon-bofang"
                @click.native.stop="handelPlay(null, 1)"
              ></icon-fonts>
            </a-tooltip>
            <a-tooltip placement="top" v-else>
              <template slot="title">
                暂停
              </template>
              <icon-fonts
                icon="icon-bofang1"
                @click.native.stop="handelPause()"
              ></icon-fonts>
            </a-tooltip>
            <a-tooltip placement="top">
              <template slot="title">
                <span>保存</span>
              </template>
              <icon-fonts
                icon="icon-baocun"
                @click.native.stop="handleSaveViewPort()"
              ></icon-fonts>
            </a-tooltip>
            <a-tooltip placement="top">
              <template slot="title">
                <span>返回</span>
              </template>
              <icon-fonts
                icon="icon-fanhui"
                @click.native.stop="handelBack()"
              ></icon-fonts>
            </a-tooltip>
          </div>
        </div>
        <div class="viewport-text">
          <a-input
            placeholder="请输入"
            v-model="form.roamName"
            @change="isChange = true"
          ></a-input>
        </div>
        <div class="viewport-list">
          <div class="empty-tip" v-if="viewportSource.length == 0">
            <a-empty :description="false" />
          </div>
          <div
            class="list-item"
            :class="
              roamIndex == index && isPlay['viewportRoam_uuid'] && 'active'
            "
            v-for="(item, index) in viewportSource"
            :key="index"
          >
            <div class="item-header">
              <icon-fonts icon="icon-tuozhuai"></icon-fonts>
              <span>{{ item.viewportName }}</span>
            </div>
            <div class="item-body">
              <div class="thumbnail">
                <img :src="item.viewportImage" v-if="item.viewportImage" />
              </div>
              <a-tooltip placement="top">
                <template slot="title">
                  <span>编辑</span>
                </template>
                <a-icon
                  type="edit"
                  @click.native.stop="handleEditViewPort(item, index)"
                />
              </a-tooltip>
              <a-tooltip placement="top">
                <template slot="title">
                  <span>定位</span>
                </template>
                <icon-fonts
                  icon="icon-dingwei"
                  @click.native.stop="handleFixedViewPort(item, index)"
                ></icon-fonts>
              </a-tooltip>
              <a-tooltip placement="top">
                <template slot="title">
                  <span>更新</span>
                </template>
                <icon-fonts
                  icon="icon-gengxin"
                  @click.native.stop="handleUpdateViewPort(item, index)"
                ></icon-fonts>
              </a-tooltip>
              <a-tooltip placement="top">
                <template slot="title">
                  <span>删除</span>
                </template>
                <a-icon
                  type="delete"
                  @click.native.stop="handleDelateViewPort(index)"
                />
              </a-tooltip>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 视口编辑弹窗 -->
    <updateRoamViewportModal
      :visible.sync="updateModalVisible"
      :parameter="updateSoucre"
      @ok="updateOk"
    ></updateRoamViewportModal>
  </div>
</template>

<script>
import updateRoamViewportModal from "./updateRoamViewportModal";
import {
  getRoamList,
  saveOrUpdateRoam,
  deleteRoam,
  detailRoam,
} from "@/api/bim";
export default {
  name: "roamDrawer",
  inject: ["currentProject", "sceneSource"],
  components: {
    updateRoamViewportModal,
  },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      //路径
      isRoute: false,
      routeSource: [],
      isPlay: {},
      routeCount: 0,
      //视口
      viewportSource: [],
      viewportCount: 0,
      isChange: false,
      viewportRomaPlay: false,
      form: {
        proCode: "",
        projid: "",
        roamName: "",
        bimRoamChildren: [],
      },
      //编辑弹窗
      updateModalVisible: false,
      updateSoucre: {},
      uuid: "",
      //漫游
      roamIndex: 0,
      currentRoamSource: {},
      roamStopFlag: true,
    };
  },
  watch: {
    visible: {
      handler(val) {
        if (val) {
          this.getRoamData();
        }
      },
      immediate: true,
    },
  },
  methods: {
    //播放
    handelPlay(item = {}, type) {
      let { bimRoamChildren, uuid } = item ?? {};
      let source = [];
      if (type) {
        source = this.viewportSource;
      } else {
        source = bimRoamChildren;
      }
      if (source && source.length >= 2) {
        if (!type) {
          this.viewportRomaPlay = false;
          this.$set(this, "isPlay", { [uuid]: true });
          this.startRoam(item);
        } else {
          this.viewportRomaPlay = true;
          this.$set(this, "isPlay", { ["viewportRoam_uuid"]: true });
          this.startRoam({
            bimRoamChildren: source,
            uuid: "viewportRoam_uuid",
          });
        }
      } else {
        this.$message.warning("请先新增视口！");
      }
    },

    //开始漫游
    startRoam(cameraData = {}) {
      let { bimRoamChildren, uuid } = cameraData;
      if (uuid != this.currentRoamSource.uuid) {
        this.roamIndex = 0;
      }
      this.currentRoamSource = cameraData;
      this.roamStopFlag = false;
      document.addEventListener("RELocateCam", this.RELocateCam);
      //定位到起始视口位置
      let { camPos, camRotate, camDir } =
        bimRoamChildren?.[this.roamIndex] ?? {};
      this.fixedToViewport(
        {
          camPos: JSON.parse(camPos),
          camRotate: JSON.parse(camRotate),
          camDir: JSON.parse(camDir),
        },
        0,
        0
      );
    },

    RELocateCam() {
      let { currentRoamSource, roamStopFlag } = this;
      if (roamStopFlag) {
        return;
      }
      this.roamIndex++;
      let { bimRoamChildren, speed } = currentRoamSource;
      if (this.roamIndex < bimRoamChildren.length) {
        let { camPos, camRotate, camDir } =
          bimRoamChildren?.[this.roamIndex] ?? {};
        this.fixedToViewport(
          {
            camPos: JSON.parse(camPos),
            camRotate: JSON.parse(camRotate),
            camDir: JSON.parse(camDir),
          },
          0,
          -Number(speed ?? 100)
        );
      } else {
        this.roamIndex = 0;
        this.roamStopFlag = false;
        this.$set(this, "isPlay", {});
      }
    },

    //定位
    handleFixedViewPort(item = {}) {
      let { camPos, camRotate, camDir } = item;
      this.roamStopFlag = true;
      this.$set(this, "isPlay", {});
      document.removeEventListener("RELocateCam", this.RELocateCam);
      this.fixedToViewport(
        {
          camPos: JSON.parse(camPos),
          camRotate: JSON.parse(camRotate),
          camDir: JSON.parse(camDir),
        },
        0,
        0
      );
    },

    //更新视口
    handleUpdateViewPort(item = {}, index = 0) {
      let { camDir, camPos, camRotate } = BlackHole3D.Camera.getCamLocate();
      this.viewportSource.forEach((v, i) => {
        if (i == index) {
          const canvas = document.getElementById("blackHoleCanvas");
          if (canvas) {
            const context = canvas.getContext("2d");
            const dataUrl = canvas.toDataURL();
            this.$set(v, "viewportImage", dataUrl);
          }
          this.$set(v, "camDir", JSON.stringify(camDir));
          this.$set(v, "camPos", JSON.stringify(camPos));
          this.$set(v, "camRotate", JSON.stringify(camRotate));
        }
      });
      //viewportSource
    },

    //定位到指定视口
    fixedToViewport(camLoc = {}, locDelay = 0, locTime = 0) {
      try {
        let camLocInstance = new BlackHole3D.RECamLoc();
        let { camPos, camRotate, camDir } = camLoc;
        camLocInstance.camPos = camPos;
        camLocInstance.camRotate = camRotate;
        camLocInstance.camDir = camDir;
        BlackHole3D.Camera.setCamLocateTo(camLocInstance, locDelay, locTime);
      } catch (error) {}
    },

    //暂停
    handelPause(item = {}) {
      let { uuid } = item;
      this.roamStopFlag = true;
      this.$set(this, "isPlay", { [uuid ?? "viewportRoam_uuid"]: false });
    },
    //停止
    handelStop() {
      this.roamStopFlag = true;
      this.currentRoamSource = {};
      this.roamIndex = 0;
      this.$set(this, "isPlay", {});
      //恢复模式视口视角 TODO...
    },

    //路径新增
    handleAddRoute() {
      this.isRoute = true;
      let { orgCode } = this.currentProject();
      this.form.proCode = orgCode;
      this.form.projid = "";
      this.routeCount++;
      this.form.roamName = "线路" + this.routeCount;
      this.form.bimRoamChildren = this.viewportSource;
      this.saveOrUpdateRoam(this.form).then((res) => {
        if (res.statusCode === 200 || res === 1) {
          this.uuid = res.data;
          this.getDetail(res.data);
        } else {
          this.$message.error(res.message);
        }
      });
    },

    //路径编辑
    handleEditRoute(item) {
      let { uuid } = item;
      this.uuid = uuid;
      this.isRoute = true;
      this.getDetail(this.uuid);
    },

    //路径删除
    handleDelateRoute(item) {
      let that = this;
      let { uuid } = item;
      that.$confirm({
        title: "提示",
        content: "确定删除该数据吗？删除之后不可恢复！",
        okText: "确定",
        cancelText: "取消",
        icon: () =>
          that.$createElement("a-icon", {
            props: {
              key: "warning",
              type: "exclamation-circle",
              twoToneColor: "#faad14",
            },
          }),
        onOk() {
          deleteRoam({ uuid })
            .then((res) => {
              if (res.statusCode === 200 || res === 1) {
                that.$message.success("删除成功", 1.5);
                that.routeSource = that.routeSource.filter(
                  (v) => v.uuid != uuid
                );
              } else {
                that.$message.error(res.message);
              }
            })
            .catch((_) => {});
        },
      });
    },

    //返回
    handelBack() {
      if (!this.isChange) {
        this.isRoute = false;
        setTimeout(() => {
          this.getRoamData();
          this.resetForm();
        }, 300);
        return;
      }
      let that = this;
      that.$confirm({
        title: "提示",
        content: "正在退出漫游视口编辑，退出前是否保存？",
        okText: "确定",
        cancelText: "取消",
        icon: () =>
          that.$createElement("a-icon", {
            props: {
              key: "warning",
              type: "exclamation-circle",
              twoToneColor: "#faad14",
            },
          }),
        onOk() {
          that
            .saveOrUpdateRoam(that.form)
            .then((res) => {
              if (res.statusCode === 200 || res === 1) {
                that.isRoute = false;
                setTimeout(() => {
                  that.getRoamData();
                  that.resetForm();
                }, 300);
              } else {
                that.$message.error(res.message);
              }
            })
            .catch((_) => {});
        },
        onCancel() {
          that.isRoute = false;
          that.getRoamData();
          that.resetForm();
        },
      });
    },

    //查询路径列表
    getRoamData() {
      return new Promise((resolve, reject) => {
        let { orgCode } = this.currentProject();
        let { sceneId } = this.sceneSource();
        getRoamList({ proCode: orgCode, sceneId })
          .then((res) => {
            this.routeSource = res?.data ?? [];
            this.routeCount = this.routeSource.length;
            this.routeSource.forEach((item) => {
              this.$set(item, "speed", "100.0");
            });
            resolve();
          })
          .catch((_) => {
            this.routeSource = [];
            reject();
          });
      });
    },

    //查询详情
    getDetail(uuid = "") {
      return new Promise((resolve, reject) => {
        detailRoam({ uuid })
          .then((res) => {
            let { roamName, proCode, bimRoamChildren = [], projid } = res;
            this.form.proCode = proCode;
            this.form.projid = projid;
            this.form.roamName = roamName;
            this.form.uuid = uuid;
            this.form.bimRoamChildren = bimRoamChildren;
            //视口
            this.viewportSource = bimRoamChildren;
            this.viewportCount = this.viewportSource.length;
            resolve();
          })
          .catch((_) => {
            reject();
          });
      });
    },

    //新增、编辑
    saveOrUpdateRoam(data = {}) {
      let { sceneId } = this.sceneSource();
      return new Promise((resolve, reject) => {
        saveOrUpdateRoam({ sceneId, ...data })
          .then((res) => {
            resolve(res);
          })
          .catch((_) => {
            reject();
          });
      });
    },

    //保存视口
    handleSaveViewPort() {
      let that = this;
      that.$confirm({
        title: "提示",
        content: "确定保存该漫游路径吗？",
        okText: "确定",
        cancelText: "取消",
        icon: () =>
          that.$createElement("a-icon", {
            props: {
              key: "warning",
              type: "exclamation-circle",
              twoToneColor: "#faad14",
            },
          }),
        onOk() {
          that.isChange = false;
          that.form.bimRoamChildren = that.viewportSource;
          that
            .saveOrUpdateRoam(that.form)
            .then((res) => {
              if (res.statusCode === 200 || res === 1) {
                that.$message.success("保存成功", 1.5);
                that.getDetail(that.uuid);
              } else {
                that.$message.error(res.message);
              }
            })
            .catch((_) => {});
        },
      });
    },

    //新增视口
    handleAddViewPort() {
      this.isChange = true;
      const canvas = document.getElementById("blackHoleCanvas");
      if (canvas) {
        const context = canvas.getContext("2d");
        const dataUrl = canvas.toDataURL();
        let { camDir, camPos, camRotate } = BlackHole3D.Camera.getCamLocate();
        this.viewportCount++;
        this.viewportSource.push({
          viewportImage: dataUrl,
          viewportName: "视口" + this.viewportCount,
          camPos: JSON.stringify(camPos),
          camDir: JSON.stringify(camDir),
          camRotate: JSON.stringify(camRotate),
        });
      }
    },

    // 编辑视口
    handleEditViewPort(item, index) {
      this.updateSoucre = { ...item, index };
      this.updateModalVisible = true;
    },
    // 编辑视口确定
    updateOk(data) {
      let { viewportName, index } = data;
      this.viewportSource[index].viewportName = viewportName;
      this.updateModalVisible = false;
      this.isChange = true;
    },

    //删除视口
    handleDelateViewPort(index) {
      this.isChange = true;
      this.viewportCount--;
      this.viewportSource.splice(index, 1);
    },

    //关闭
    handleClose() {
      this.$emit("update:visible", false);
      this.$emit("close", false);
      //路径
      this.isRoute = false;
      this.routeSource = [];
      this.isPlay = {};
      this.routeCount = 0;
      //视口
      this.viewportSource = [];
      this.viewportCount = 0;
      this.isChange = false;
      this.form = {
        proCode: "",
        projid: "",
        roamName: "",
        bimRoamChildren: [],
      };
      //漫游
      this.roamStopFlag = true;
      this.currentRoamSource = {};
      this.roamIndex = 0;
      this.$set(this, "isPlay", {});
    },
    resetForm() {
      this.routeCount = 0;
      this.isChange = false;
      this.viewportSource = [];
      this.form = {
        proCode: "",
        projid: "",
        roamName: "",
        bimRoamChildren: [],
      };
    },
  },
};
</script>

<style lang="less" scoped>
.roamDrawer-container {
  position: absolute;
  width: 300px;
  height: 100%;
  top: 0;
  pointer-events: none;
  transition: 0.3s;
  right: 8px;
  box-sizing: border-box;
  padding: 16px 0 20px 0;
  z-index: 99;
  &.hide {
    right: -100%;
  }
  .roamDrawer-body {
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 6px;
    pointer-events: all;
    .header {
      flex-shrink: 0;
      height: 36px;
      background: #f0f0f0;
      border-radius: 6px 6px 0px 0px;
      border: 1px solid #d9d9d9;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      padding: 0 16px;
      font-size: 16px;
      color: #333333;
      position: relative;
      .anticon-close {
        color: #8c8c8c;
        font-size: 15px;
        cursor: pointer;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        right: 10px;
      }
    }
    .body {
      flex: 1;
      background: #fff;
      padding: 16px 0 0 0;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      .empty-tip {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
      .add-route-btn {
        flex-shrink: 0;
        height: 32px;
        background: rgba(22, 119, 255, 0.1);
        border-radius: 4px 4px 4px 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #1677ff;
        font-size: 14px;
        cursor: pointer;
        margin: 0 16px 16px 16px;
        .anticon {
          font-size: 10px;
          margin: 2px 5px 0 0;
        }
      }
      .route-list {
        flex: 1;
        overflow: auto;
        padding: 0 16px 0 16px;
        position: relative;
        .list-item {
          height: 86px;
          background: #ffffff;
          border-radius: 4px 4px 4px 4px;
          border: 1px solid #f2f2f2;
          margin-bottom: 10px;
          display: flex;
          flex-direction: column;
          &:hover {
            border-color: #d9d9d9;
            box-shadow: 0px 8px 16px 0px rgba(22, 119, 255, 0.15);
            .name {
              .operate {
                display: flex;
              }
            }
          }
          .name {
            height: 32px;
            display: flex;
            align-items: center;
            font-size: 14px;
            color: #333;
            letter-spacing: 1px;
            background: #f2f2f2;
            opacity: 0.95;
            padding: 0 10px 0 10px;
            box-sizing: border-box;
            .name-text {
              flex: 1;
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
            }
            .operate {
              flex-shrink: 0;
              color: #8c8c8c;
              margin-left: 10px;
              display: none;
              .anticon {
                font-size: 16px;
                cursor: pointer;
                &:hover {
                  color: #1677ff;
                }
                &:nth-child(2) {
                  margin: 0 6px;
                }
              }
            }
          }
          .desc {
            padding: 10px;
            display: flex;
            justify-content: space-between;
            .input-number {
              display: flex;
              align-items: center;
              /deep/.ant-input-number {
                width: 110px !important;
              }
              .unit {
                font-family: Microsoft YaHei, Microsoft YaHei;
                font-weight: 400;
                font-size: 14px;
                color: #666666;
                letter-spacing: 1px;
                font-style: normal;
                margin-left: 10px;
              }
            }
            .play {
              cursor: pointer;
              display: flex;
              align-items: center;
              .middle {
                margin-right: 16px;
                font-size: 22px !important;
                &:last-of-type {
                  margin-right: 0;
                }
              }
            }
          }
        }
      }
      .viewport-header {
        margin: 0 16px 16px 16px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .name {
          font-family: Microsoft YaHei, Microsoft YaHei;
          font-weight: 400;
          font-size: 14px;
          color: #1677ff;
          position: relative;
          padding-left: 10px;
          &::before {
            content: "";
            position: absolute;
            top: 3px;
            left: 0;
            width: 3px;
            height: 16px;
            background: #1677ff;
            border-radius: 4px 4px 4px 4px;
          }
        }
        .operate {
          .anticon {
            margin-right: 10px;
            &:last-of-type {
              margin-right: 0;
            }
          }
        }
      }
      .viewport-text {
        margin: 0 16px 16px 16px;
      }
      .viewport-list {
        flex: 1;
        overflow: auto;
        padding: 0 16px 0 16px;
        position: relative;
        .list-item {
          height: 108px;
          background: #ffffff;
          border-radius: 4px 4px 4px 4px;
          border: 1px solid #f2f2f2;
          margin-bottom: 10px;
          display: flex;
          flex-direction: column;
          overflow: hidden;
          &.active {
            border-color: #1677ff;
          }
          &:hover {
            border-color: #d9d9d9;
            box-shadow: 0px 8px 16px 0px rgba(22, 119, 255, 0.15);
          }
          .item-header {
            height: 32px;
            display: flex;
            align-items: center;
            font-size: 14px;
            color: #333;
            letter-spacing: 1px;
            background: #f2f2f2;
            opacity: 0.95;
            padding: 0 10px 0 10px;
            box-sizing: border-box;
            span {
              margin-left: 8px;
              padding-bottom: 2px;
            }
          }
          .item-body {
            padding: 10px;
            display: flex;
            align-items: center;
            .thumbnail {
              flex-shrink: 0;
              width: 96px;
              height: 54px;
              border-radius: 4px 4px 4px 4px;
              margin-right: 20px;
              img {
                width: 100%;
                height: 100%;
                object-fit: contain;
              }
            }
            .anticon {
              cursor: pointer;
              font-size: 20px !important;
              margin-right: 14px;
              &:last-of-type {
                margin-right: 0;
              }
            }
          }
        }
      }
    }
  }
}
</style>
